'''
    exercise one: 函数与默认值
    说明：默认值只会被执行一次
'''


def func(a, L=[]):
    L.append(a)
    return L


# 调用func
print(func(1))
print(func(2))
print(func(3))
# 输出结果是如下，因为默认值L只会执行一次,多次调用L的地址不变，所以会将其余的a添加到同一个L中
# [1]
# [1, 2]
# [1, 2, 3]
print("\n-------------------------------------------------------\n")

'''
    exercise two: 关键字参数 kwarg=value
'''


def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
    print("-- This parrot wouldn't", action, end=' ')
    print("if you put", voltage, "volts through it.")
    print("-- Lovely plumage, the", type)
    print("-- It's", state, "!")


parrot(300)
print("\n-------------------------------------------------------\n")

'''
    exercise three:
    *name
    **name的使用
'''
print("\n-----------------------[3]--------------------------------\n")


def myClass(serialno, *classInfo, **classmateInfo):
    print("serialno: ", serialno, end="\n")
    for item in classInfo:
        print(item, end=' ')
    print("\n")
    for kw in classmateInfo:
        print(kw, classmateInfo[kw], end='\t')


myClass(1001, '火箭班', '45人', age=20, sex='male', name='张一山')
print("\n-------------------------------------------------------\n")

'''
    exercise four:
    使用/或* 指定哪些使用key,哪些是位置参数，哪些是都可以
'''


def combined_example(pos_only, /, standard, *, kwd_only):
    print(pos_only, standard, kwd_only)


combined_example(22, standard=2, kwd_only=3)
print("\n-------------------------------------------------------\n")

'''
    exercise five:
    仅限位置形参的名称可以在 **kwds 中使用而不产生歧义。
'''

print("\n-------------------------------------------------------\n")


def foo(name, **kwds):
    return 'name' in kwds


print(foo(1, bb=2))
print(foo(1, **{'bb': 2}))


def foo_d(name, /, **kwds):
    return name in kwds


foo_d(1, name=2)
foo_d(2, **{'name': 3})
print("\n-------------------------------------------------------\n")

'''
    str.join(a),string的参数只能有一个,一个可遍历的对象。但是这个只能是str类型的
    
    map函数: 第一个参数是函数，第二个参数是一个可遍历的元素集合比如元组、列表
            但是如果直接写map(func,list)...这样是不会触发lambda计算的，是惰性计算的
            所以下面的例子中使用list()触发其计算
    lambda使用: 和java中的lambda/前端lambda有点不一样,语法上: lambda param: expression(param), 或者将内置函数也可以作为lambda使用
'''


def concat(*args, sep="/"):
    return sep.join(args)


print(concat("D:", "Application", "Tools", "Intellij"))
ss = "/"
list1 = ['1', '2', '3', '3']
# mapStr=map(lambda aa: str(aa), list)
ii = [1, 2, 3, 4]
lists = []
list(map(lambda x: lists.append(str(x)), ii))
print(ss.join(lists))
print("第二种方法: ")
print(ss.join([str(x) for x in ii]))
print("\n-------------------------------------------------------\n")

'''
    exercise sex:解包
    * 解包 列表或元组
    ** 解包 字典
'''


def parrot(voltage, state='a stiff', action='voom'):
    print("This parrot wouldn't ", action, end=' ')
    print('if you put ', voltage, "volts through it.", end=" ")
    print("E s ", state, "!")


d = {"voltage": "four million", "state": "bleedin ' demised", "action": "VOOM"}
# 字典解包
parrot(**d)

print("\n-------------------------------------------------------\n")

'''
    Lambda表达式
    正常函数的语法糖，与嵌套函数定义一样，lambda函数可以引用所包含域的变量。
    类似于一个匿名函数哦~
'''


def make_incrementor(n):
    return lambda x: x + n


f = make_incrementor(43)
print(f(0))
print(f(3))
print(f(1))

print("\n-------------------------------------------------------\n")

pairs = [(1, 'one'), (2, 'two'), (5, 'five'), (4, 'four')]
pairs.sort(key=lambda item: item[0])
print(pairs)
print("\n-------------------------------------------------------\n")

'''
    exercise seven:
    函数标注, 以字典的形式存放在函数的 __annotations__ 属性中
    并且不会影响函数的任何其他部分
    返回值类型 -> type:
'''


def f(ham: str, eggs: str = 'eggs') -> str:
    print("Annotations: ", f.__annotations__)
    print("Arguments: ", ham, eggs)
    return ham + ' and ' + eggs

f('spam')

'''
    exercise eight: 代码规范
    以一致的规则为你的类和函数命名；按照惯例应使用 UpperCamelCase 来命名类，而以 lowercase_with_underscores 来命名函数和方法。
    始终应使用 self 来命名第一个方法参数 (有关类和方法的更多信息请参阅 初探类)。
    
    Python 默认的 UTF-8 或者纯 ASCII 在任何情况下都能有最好的表现。
    
    实际上，通过对象引用调用 会是一个更好的表述，因为如果传递的是可变对象，则调用者将看到被调用者对其做出的任何更改（插入到列表中的元素）。
'''